Here follows a collection of useful C# links/bookmarks.
We hope that they are useful for you.
Update GUI from worker thread
Overview:
- http://stackoverflow.com/questions/2097284/update-ui-from-multiple-worker-threads-net
The code below is excellent for Windows Forms and needs just a little modification for WPF!! Taken from: http://stackoverflow.com/questions/661561/how-to-update-gui-from-another-thread-in-c:
using System;
using System.Windows.Forms;
using System.Threading;
namespace Test
{
public partial class UIThread : Form
{
Worker worker;
Thread workerThread;
public UIThread()
{
InitializeComponent();
worker = new Worker();
worker.ProgressChanged += new EventHandler<ProgressChangedArgs>(OnWorkerProgressChanged);
workerThread = new Thread(new ThreadStart(worker.StartWork));
workerThread.Start();
}
private void OnWorkerProgressChanged(object sender, ProgressChangedArgs e)
{
//cross thread – so you don’t get the cross theading exception
if (this.InvokeRequired)
{
this.BeginInvoke((MethodInvoker)delegate
{
OnWorkerProgressChanged(sender, e);
});
return;
}
//change control
this.label1.Text = e.Progress;
}
}
public class Worker
{
public event EventHandler<ProgressChangedArgs> ProgressChanged;
protected void OnProgressChanged(ProgressChangedArgs e)
{
if(ProgressChanged!=null)
{
ProgressChanged(this,e);
}
}
public void StartWork()
{
Thread.Sleep(100);
OnProgressChanged(new ProgressChangedArgs(“Progress Changed”));
Thread.Sleep(100);
}
}
public class ProgressChangedArgs : EventArgs
{
public string Progress {get;private set;}
public ProgressChangedArgs(string progress)
{
Progress = progress;
}
}
}
WPF Dispatcher.BeginInvoke: http://msdn.microsoft.com/en-us/library/ms591587.aspx
Thread safe GUI: http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).asp
By using BackgroundWorker:
- http://stackoverflow.com/questions/2097284/update-ui-from-multiple-worker-threads-net
- http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
- http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
Threading
- Microsoft overview: http://msdn.microsoft.com/en-us/library/ms741870.aspx
- Thread synchronization: http://msdn.microsoft.com/en-us/library/ms173179.aspx
- Threading in C#: http://www.albahari.com/threading/
- events and thread safty: http://stackoverflow.com/questions/786383/c-sharp-events-and-thread-safety
- .Net 2003: http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
- http://www.knowdotnet.com/articles/responsiveui.html
- http://www.codeproject.com/Articles/1280/Worker-Threads-in-C
Invoke/BeginInvoke
Difference between “Invoke” and “BeginInvoke”:
- http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke
Logging
- http://csharp-source.net/open-source/logging
C# tutorials
1. .Net 2003: http://msdn.microsoft.com/en-us/library/aa288436(v=vs.71).aspx
Events and delegates
- .Net 2003: http://msdn.microsoft.com/en-us/library/aa288436(v=vs.71).aspx
Interfaces
- http://www.daniweb.com/software-development/csharp/threads/114364
- http://fci-h.blogspot.com/2008/03/oop-design-concepts-interfaces_05.html
SendInput
http://www.ownedcore.com/forums/world-of-warcraft/world-of-warcraft-bots-programs/wow-bots-questions-requests/317470-c-sendinput-blocked.html
public class Input
{
private static InputWrapper KeyboardWrapper(ushort scanCode, bool keyUp)
{
InputWrapper wrapper = new InputWrapper();
wrapper.Type = SendInputType.Keyboard;
wrapper.MKH.Keyboard = new KeyboardInputData()
{
Key = 0,
Scan = scanCode,
Flags = (uint)KeyboardFlags.ScanCode,
Time = 0,
ExtraInfo = IntPtr.Zero
};
if (keyUp)
wrapper.MKH.Keyboard.Flags |= (uint)KeyboardFlags.KeyUp;
return wrapper;
}
public static void SimulateKeyPress(ushort scanCode, bool shift, bool ctrl, bool alt)
{
List<InputWrapper> inputs = new List<InputWrapper>();
// Add the key down and up
inputs.Add(KeyboardWrapper(scanCode, false));
inputs.Add(KeyboardWrapper(scanCode, true));
// For each of the modifier keys, put a key down before and key up after the key we’re simulating
if (shift)
{
inputs.Insert(0, KeyboardWrapper((ushort)DirectXScanCode.DIK_LSHIFT, false));
inputs.Add(KeyboardWrapper((ushort)DirectXScanCode.DIK_LSHIFT, true));
}
if (ctrl)
{
inputs.Insert(0, KeyboardWrapper((ushort)DirectXScanCode.DIK_LCONTROL, false));
inputs.Add(KeyboardWrapper((ushort)DirectXScanCode.DIK_LCONTROL, true));
}
if (alt)
{
inputs.Insert(0, KeyboardWrapper((ushort)DirectXScanCode.DIK_LMENU, false));
inputs.Add(KeyboardWrapper((ushort)DirectXScanCode.DIK_LMENU, true));
}
// Send the list of inputs to the foreground application
SendInput((uint)inputs.Count, inputs.ToArray(), Marshal.SizeOf(typeof(InputWrapper)));
}
[DllImport(“user32.dll”, SetLastError = true)]
static extern uint SendInput(uint numberInputs, InputWrapper[] inputs, int sizeOfStructure);
[StructLayout(LayoutKind.Sequential)]
private struct InputWrapper
{
public SendInputType Type;
public MouseKeyboardHardwareUnion MKH;
}
private enum SendInputType : int
{
Mouse = 0,
Keyboard,
Hardware
}
[StructLayout(LayoutKind.Explicit)]
private struct MouseKeyboardHardwareUnion
{
[FieldOffset(0)]
public MouseInputData Mouse;
[FieldOffset(0)]
public KeyboardInputData Keyboard;
[FieldOffset(0)]
public HardwareInputData Hardware;
}
[StructLayout(LayoutKind.Sequential)]
private struct MouseInputData
{
public int X;
public int Y;
public uint MouseData;
public MouseEventFlags Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
private struct KeyboardInputData
{
public ushort Key;
public ushort Scan;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
private struct HardwareInputData
{
public int Msg;
public short ParamL;
public short ParamH;
}
[Flags]
enum MouseDataFlags : uint
{
XButton1 = 0x0001,
XButton2 = 0x0002
}
[Flags]
enum KeyboardFlags : uint
{
ExtendedKey = 0x1,
KeyUp = 0x2,
Unicode = 0x4,
ScanCode = 0x8
}
[Flags]
enum MouseEventFlags : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesktop = 0x4000,
Absolute = 0x8000
}
public enum DirectXScanCode : ushort
{
DIK_ESCAPE = 0x01,
DIK_1 = 0x02,
DIK_2 = 0x03,
DIK_3 = 0x04,
DIK_4 = 0x05,
DIK_5 = 0x06,
DIK_6 = 0x07,
DIK_7 = 0x08,
DIK_8 = 0x09,
DIK_9 = 0x0A,
DIK_0 = 0x0B,
DIK_MINUS = 0x0C, /* – on main keyboard */
DIK_EQUALS = 0x0D,
DIK_BACK = 0x0E, /* backspace */
DIK_TAB = 0x0F,
DIK_Q = 0x10,
DIK_W = 0x11,
DIK_E = 0x12,
DIK_R = 0x13,
DIK_T = 0x14,
DIK_Y = 0x15,
DIK_U = 0x16,
DIK_I = 0x17,
DIK_O = 0x18,
DIK_P = 0x19,
DIK_LBRACKET = 0x1A,
DIK_RBRACKET = 0x1B,
DIK_RETURN = 0x1C, /* Enter on main keyboard */
DIK_LCONTROL = 0x1D,
DIK_A = 0x1E,
DIK_S = 0x1F,
DIK_D = 0x20,
DIK_F = 0x21,
DIK_G = 0x22,
DIK_H = 0x23,
DIK_J = 0x24,
DIK_K = 0x25,
DIK_L = 0x26,
DIK_SEMICOLON = 0x27,
DIK_APOSTROPHE = 0x28,
DIK_GRAVE = 0x29, /* accent grave */
DIK_LSHIFT = 0x2A,
DIK_BACKSLASH = 0x2B,
DIK_Z = 0x2C,
DIK_X = 0x2D,
DIK_C = 0x2E,
DIK_V = 0x2F,
DIK_B = 0x30,
DIK_N = 0x31,
DIK_M = 0x32,
DIK_COMMA = 0x33,
DIK_PERIOD = 0x34, /* . on main keyboard */
DIK_SLASH = 0x35, /* / on main keyboard */
DIK_RSHIFT = 0x36,
DIK_MULTIPLY = 0x37, /* * on numeric keypad */
DIK_LMENU = 0x38, /* left Alt */
DIK_SPACE = 0x39,
DIK_CAPITAL = 0x3A,
DIK_F1 = 0x3B,
DIK_F2 = 0x3C,
DIK_F3 = 0x3D,
DIK_F4 = 0x3E,
DIK_F5 = 0x3F,
DIK_F6 = 0x40,
DIK_F7 = 0x41,
DIK_F8 = 0x42,
DIK_F9 = 0x43,
DIK_F10 = 0x44,
DIK_NUMLOCK = 0x45,
DIK_SCROLL = 0x46, /* Scroll Lock */
DIK_NUMPAD7 = 0x47,
DIK_NUMPAD8 = 0x48,
DIK_NUMPAD9 = 0x49,
DIK_SUBTRACT = 0x4A, /* – on numeric keypad */
DIK_NUMPAD4 = 0x4B,
DIK_NUMPAD5 = 0x4C,
DIK_NUMPAD6 = 0x4D,
DIK_ADD = 0x4E, /* + on numeric keypad */
DIK_NUMPAD1 = 0x4F,
DIK_NUMPAD2 = 0x50,
DIK_NUMPAD3 = 0x51,
DIK_NUMPAD0 = 0x52,
DIK_DECIMAL = 0x53, /* . on numeric keypad */
DIK_F11 = 0x57,
DIK_F12 = 0x58,
}
}
class Program
{
static void Main(string[] args)
{
// You have 5 seconds to switch the application on which you’d like to receive the
// event to the foreground
Thread.Sleep(5000);
Input.SimulateKeyPress((ushort)Input.DirectXScanCode.DIK_3, false, false, false);
}
}
public static void MouseMoveBy(int x, int y)
{
InputWrapper input = new InputWrapper();
input.Type = SendInputType.Mouse;
input.MKH.Mouse = new MouseInputData()
{
X = x,
Y = y,
Flags = MouseEventFlags.Move,
};
InputWrapper[] inputs = new InputWrapper[] { input };
SendInput((uint)1, inputs, Marshal.SizeOf(typeof(InputWrapper)));
}